<template>
  <div
    class="sliders_box"
    :class="{valueVertical_box: shapeNode.model?.showAttribute.extraAttribute?.vertical}"
    :style="{
      background: shapeNode.style.background,
      width: `${sliderStyle.width}px`,
      height: `${sliderStyle.height}px`,
      position: 'absolute',
      left: `${sliderStyle.left}px`,
      top: `${sliderStyle.top}px`,
    }">
    <div class="_slider">
      <div ref="traceDom" class="_slider_trace">
        <div
          :class="[invert ? '_slider_trace_right' : '_slider_trace_left']"
          :style="{
            flex: fillWidth
          }"></div>
        <div
          :class="[invert ? '_slider_trace_left' : '_slider_trace_right']"
          :style="{
            flex: (1- fillWidth)
          }"></div>
        <div
          :style="{
            left: sliderBlockPos
          }"
          class="_slider_block"
          @mousedown.stop="sliderBlockMousedown"
        >
        </div>
      </div>
    </div>
    <div class="_scale">
      <div
        v-for="(item, index) in sliderScaleAndValue"
        :key="index"
        :style="{
          left: `${item.pos}%`
        }"
        class="_scale_item">
        <div class="_scale_item_scale">{{ item.scale }}</div>
        <div
          :class="{valueVertical: shapeNode.model?.showAttribute.extraAttribute?.vertical, lastScale: index === sliderScaleAndValue.length - 1}"
          class="_scale_item_value"
          :title="item.value">{{ item.value }}</div>
      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { ADCUICoreNode, ShapeKeyEnum } from '@/constants/types';
import { onMounted, ref, watch, computed } from 'vue';
import { controller } from "@/engine/Controller";
import { cloneDeep } from "lodash";

const props = defineProps<{
  shapeNode: ADCUICoreNode;
}>();
const { invert, knobPosition, maximumValue, minimumValue, spacing, vertical, inactive = false } = props.shapeNode.model?.showAttribute.extraAttribute as any;
const SliderBlockOffset = 6;
let blockOriginPos = 0;
let blockOriginPosPercent = 0;
const isVerticel = props.shapeNode.model?.showAttribute.extraAttribute?.vertical ? -1 : 1;
const sliderStyle = computed(() => {
  const width = props.shapeNode.model?.showAttribute.extraAttribute?.vertical ? props.shapeNode.style.height : props.shapeNode.style.width;
  const height = props.shapeNode.model?.showAttribute.extraAttribute?.vertical ? props.shapeNode.style.width : props.shapeNode.style.height;
  const left = props.shapeNode.model?.showAttribute.extraAttribute?.vertical ? (height - width) / 2 : 0;
  const top = props.shapeNode.model?.showAttribute.extraAttribute?.vertical ? (width - height) / 2 - 5 : 0;
  return {
    width,
    height,
    left,
    top
  };
});
const sliderScaleAndValue = computed(() => {
  if (props.shapeNode.shapeKey !== ShapeKeyEnum.SimulationSliders) return 0;
  const { invert, knobPosition, maximumValue, minimumValue, spacing, vertical, values } = props.shapeNode.model?.showAttribute.extraAttribute as any;
  const scaleCount = Math.floor((maximumValue - minimumValue) / spacing);
  const remainder = (maximumValue - minimumValue) % spacing;
  const sliderTotal = 90;
  const r = [] as any;
  const usedValues = [];
  if (values && values.length) {
    for (const v of values) {
      if (v && !isNaN(v)) {
        const calculated = Math.round(Number(v) * 10) / 10;
        if (calculated >= minimumValue && calculated <= maximumValue) {
          usedValues.push(Math.round(Number(v) * 10) / 10);
        }
      }
    }
  }
  for (let i = 0; i <= scaleCount; i++) {
    if (i === 0) {
      r.push({ pos: 0, value: minimumValue, scale: '|' });
    } else if (i === scaleCount && !remainder) {
      r.push({ pos: sliderTotal, value: maximumValue, scale: '|' });
    } else {
      r.push({ pos: i * spacing / (maximumValue - minimumValue) * sliderTotal, value: spacing * i + minimumValue, scale: '|' });
    }
  }
  if (remainder) {
    r.push({ pos: sliderTotal, value: maximumValue, scale: '|' });
  }
  if (usedValues.length) {
    for (const uv of usedValues) {
      r.push({ pos: (uv - minimumValue) / (maximumValue - minimumValue) * sliderTotal, value: uv, scale: '|' });
    }
  }
  if (invert) {
    for (const ir of r) {
      ir.pos = sliderTotal - ir.pos;
    }
  }
  return r;
});
const traceDom = ref<HTMLElement>();
const sliderBlockPos = ref(`calc(0% - ${SliderBlockOffset}px)`);
const fillWidth = ref(0);
const sliderBlockMousedown = (e: MouseEvent) => {
  if (props.shapeNode.model?.showAttribute.extraAttribute?.inactive) return;
  blockOriginPos = props.shapeNode.model?.showAttribute.extraAttribute?.vertical ? e.clientY : e.clientX;
  if (e.target && e.target instanceof HTMLElement) {
    if (props.shapeNode.model?.showAttribute.extraAttribute?.vertical) {
      blockOriginPosPercent = 1 - (e.target.getBoundingClientRect().y + SliderBlockOffset - (traceDom.value)!.getBoundingClientRect().y) / (traceDom.value)!.getBoundingClientRect().height;
    } else {
      blockOriginPosPercent = (e.target.getBoundingClientRect().x + SliderBlockOffset - (traceDom.value)!.getBoundingClientRect().x) / (traceDom.value)!.getBoundingClientRect().width;
    }
  }
  document.addEventListener('mousemove', sliderBlockMousemove);
  document.addEventListener('mouseup', sliderBlockMouseup);
};
const sliderBlockMouseup = (e: MouseEvent) => {
  document.removeEventListener('mousemove', sliderBlockMousemove);
  blockOriginPos = 0;
  const nowData = (maximumValue - minimumValue) * fillWidth.value;
  let changingData = invert
    ? Math.round((maximumValue - nowData) * 10) / 10
    : Math.round((minimumValue + nowData) * 10) / 10;
  if (props.shapeNode.valueType === "Integer") {
    changingData = Math.round(changingData);
  }
  controller.simUIService.uiDataChangeNoteBackend(props.shapeNode.objectId, props.shapeNode.propertyId, [changingData]);
};
const sliderBlockMousemove = (e: MouseEvent) => {
  const usedMousePos = props.shapeNode.model?.showAttribute.extraAttribute?.vertical ? e.clientY : e.clientX;
  const usedSliderWidth =  props.shapeNode.model?.showAttribute.extraAttribute?.vertical ? props.shapeNode.style.height * 0.9 : props.shapeNode.style.width * 0.9;
  fillWidth.value = blockOriginPosPercent + isVerticel * (usedMousePos - blockOriginPos) / usedSliderWidth;
  if (fillWidth.value >= 0 && fillWidth.value <= 1) {
    sliderBlockPos.value = `calc(${fillWidth.value * 100}% - ${SliderBlockOffset}px)`;
  } else if (fillWidth.value < 0) {
    fillWidth.value = 0;
  } else if (fillWidth.value > 1) {
    fillWidth.value = 1;
  }
  console.log(`usedMousePos: ${usedMousePos}, blockOriginPos: ${blockOriginPos}, sliderBlockPos:${sliderBlockPos.value}`);
};
const dealDefaultValue = (v: number) => {
  if (v) {
    if (v <= minimumValue) {
      fillWidth.value = 0;
    } else if (v >= maximumValue) {
      fillWidth.value = 1;
    } else {
      fillWidth.value = (v - minimumValue) / (maximumValue - minimumValue);
    }
  } else {
    fillWidth.value = 0;
  }
  fillWidth.value = invert ? 1 - fillWidth.value : fillWidth.value;
  sliderBlockPos.value = `calc(${fillWidth.value * 100}% - ${SliderBlockOffset}px)`;
};

onMounted(() => {
  const { knobPosition } = props.shapeNode.model?.showAttribute.extraAttribute;
  dealDefaultValue(Number(props.shapeNode.propertyData.value) || knobPosition);
});

watch(
  () => props.shapeNode.propertyData,
  () => {
    dealDefaultValue(Number(props.shapeNode.propertyData.value));
  },
  { deep: true }
);
</script>
<style lang="scss" scoped>
.inactive {
  .sliders_box {
    ._slider {
      cursor: not-allowed;
      ._slider_trace {
        ._slider_trace_left {
          background: #999;
          cursor: not-allowed;
        }
      }
      ._slider_block {
        border: 2px solid #999;
        cursor: not-allowed;
      }
    }
  }
}
.valueVertical_box {
    transform: rotate(-90deg);
  }
.sliders_box{
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
  .valueVertical {
    transform: rotate(90deg);
    transform-origin: center;
  }
  ._slider {
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-left: 5%;
    padding-right: 5%;
    position: relative;
    ._slider_trace {
      width: 100%;
      height: 6px;
      position: relative;
      display: flex;
      border-radius: 6px;
      background: rgba($color: #D0D0D0, $alpha: .5);
      ._slider_trace_left {
        height: 6px;
        background: #1890FF;
        border-radius: 6px;
      }
      ._slider_trace_right {
        height: 6px;
        border-radius: 6px;
      }
    }
    ._slider_block {
      width: 12px;
      height: 12px;
      position: absolute;
      left: 0;
      top: -5px;
      display: flex;
      flex-direction: column;
      z-index: 10;
      overflow: hidden;
      border: 2px solid #1890FF;
      cursor: pointer;
      background: #fff;
      border-radius: 8px;
    }
  }
  ._scale {
    position: relative;
    padding-bottom: 6px;
    height: 16px;
    ._scale_item {
      width: 10%;
      text-align: center;
      position: absolute;
      top: 0;
      left: 0;
      ._scale_item_scale {
        width: 100%;
        height: 6px;
        font-size: 6px;
        text-align: center;
        color: #999;
      }
      ._scale_item_value {
        width: 100%;
        height: 10px;
        font-size: 10px;
        text-align: center;
        margin-top: 4px;

        &.lastScale {
          overflow: hidden;
          text-overflow: ellipsis;
        }
      }
    }
  }
  ._scale_value {
    width: 100%;
  }
}
</style>